package main

import (
	"errors"
	"strconv"
	"strings"
	//"tuowei.com/pkg/baliance.com/gooxml/document"
)

const (
	// 选项分隔符
	OptionSeparator = "."
	// 答案分隔符
	AnswerSeparator = ":"
	// 分数分隔符
	ScoreSeparator = ":"
	// 题型分隔符
	SubTypeSeparator = ":"
	// 解析分割符
	AnalysisSeparator = ":"

	// 图片占位符
	ImagePlaceholder = "{{}}"
)

type subject struct {
	Title         string   `json:"title" comment:"标题"`
	Options       []Option `json:"options" comment:"答案选项"`
	CorrectAnswer []string `json:"correct_answer" comment:"正确答案"`
	Score         float64  `json:"score" comment:"分值"`
	SubjectType   string   `json:"subject_type" comment:"题目类型"`
	Analysis      string   `json:"analysis" comment:解析""`
}

func (sub *subject) Reset() {
	sub.Title = ""
	sub.Options = make([]Option, 0)
	sub.CorrectAnswer = make([]string, 0)
	sub.Score = 0
	sub.SubjectType = ""
	sub.Analysis = ""
}
func (sub *subject) IsEmpty() bool {
	return sub.Title == ""
}

// string方法返回该字段的全部字符串
// 图片只能存在与题干和答案，还有解析之中
func String(subjects []subject) string {
	builder := strings.Builder{}
	for _, sub := range subjects {
		builder.WriteString(sub.Title)
		builder.WriteString(strings.Join(sub.CorrectAnswer, ""))
		builder.WriteString(sub.Analysis)
		for _, op := range sub.Options {
			builder.WriteString(op.Explain)
		}
	}
	return builder.String()
}

type Option struct {
	// 选项 A,B,C,D
	Opt     string `json:"opt"`
	Explain string `json:"explain"`
}

// line 每道题的段落号
// str 需要处理的段落字符串
func (sub *subject) DealGraph(line int, str string) error {
	var err error
	if sub.IsOption(str) {
		// 选项
		if err = sub.Option(str); err != nil {
			return err
		}
	} else if sub.IsAnswer(str) {
		if err = sub.Answer(str); err != nil {
			return err
		}
	} else if sub.IsScore(str) {
		if err = sub.Scores(str); err != nil {
			return err
		}
	} else if sub.IsSubType(str) {
		sub.SubType(str)
	} else if sub.IsAnalysis(str) {
		sub.Analyze(str)
	} else {
		// 作为标题
		sub.Title = str
	}
	return nil
}

// 判断是否是选项
// 如果是则返回选项的结果
func (sub *subject) Option(str string) error {
	optionStr := str[:2]
	arr := strings.Split(optionStr, ".")
	opt := arr[0]
	for _, v := range sub.Options {
		// 存在相同选项
		if v.Opt == opt {
			return errors.New("已经存在相同答案选项")
		}
	}
	sub.Options = append(sub.Options, Option{
		Opt:     arr[0],
		Explain: str[2:],
	})
	return nil
}

// 是否是选项
func (sub *subject) IsOption(str string) bool {
	return strings.HasPrefix(str, "A"+OptionSeparator) ||
		strings.HasPrefix(str, "B"+OptionSeparator) ||
		strings.HasPrefix(str, "C"+OptionSeparator) ||
		strings.HasPrefix(str, "D"+OptionSeparator)
}
func (sub *subject) IsAnswer(str string) bool {
	ok := strings.HasPrefix(str, "答案"+AnswerSeparator)
	if ok {
	}
	return ok
}
func (sub *subject) Answer(str string) error {
	if len(sub.CorrectAnswer) > 0 {
		return errors.New("格式错误:该题目已经有答案")
	}
	runeStr := []rune(str)
	sub.CorrectAnswer = strings.Split(string(runeStr[3:]), "")
	return nil
}

// 是否是分数
func (sub *subject) IsScore(str string) bool {
	return strings.HasPrefix(str, "分数"+ScoreSeparator)
}

func (sub *subject) Scores(str string) error {
	if sub.Score > 0 {
		return errors.New("格式错误:该题目已经有分数了")
	}
	runeStr := []rune(str)

	if score, err := strconv.ParseFloat(string(runeStr[3:]), 64); err != nil {
		return errors.New("分数必须是一个数字")
	} else {
		sub.Score = score
	}
	return nil
}

// 是否是题型
func (sub *subject) IsSubType(str string) bool {
	return strings.HasPrefix(str, "题型"+SubTypeSeparator)
}
func (sub *subject) SubType(str string) {
	runeStr := []rune(str)
	sub.SubjectType = string(runeStr[3:])
}

// 是否是解析
func (sub *subject) IsAnalysis(str string) bool {
	return strings.HasPrefix(str, "解析"+AnalysisSeparator)
}
func (sub *subject) Analyze(str string) {
	runeStr := []rune(str)
	sub.Analysis = string(runeStr[3:])
}

//func Parse(f *os.File) ([]subject, error) {
//	subjects := make([]subject, 0)
//	fileInfo, err := f.Stat()
//	if err != nil {
//		return subjects, err
//	}
//	doc, err := document.Read(f, fileInfo.Size())
//	if err != nil {
//		return subjects, err
//	}
//	builder := strings.Builder{}
//	sub := &subject{}
//	// 段落字符串
//	graph := ""
//	// 第几题
//	num := 0
//	lengh := len(doc.Paragraphs())
//	// 解析文本
//	for line, para := range doc.Paragraphs() {
//		for _, run := range para.Runs() {
//			builder.WriteString(run.Text())
//		}
//		graph = strings.TrimSpace(builder.String())
//		if line == lengh-1 && graph != "" {
//			return subjects, errors.New("最后一行必须是空行")
//		}
//
//		builder.Reset()
//		// 遇空行意味着是新的一题
//		if graph == "" {
//			if !sub.IsEmpty() {
//				num++
//				subjects = append(subjects, *sub)
//				sub.Reset()
//			}
//			continue
//		}
//		fmt.Printf("%d = %s\n", line, graph)
//		err = sub.DealGraph(line, graph)
//		if err != nil {
//			return subjects, fmt.Errorf("第%d段错误 %v", line, err)
//		}
//	}
//
//	// 检测占位符数量和图片数量是否匹配
//	holderNum := strings.Count(String(subjects), ImagePlaceholder)
//	imageNum := len(doc.Images)
//	if holderNum != imageNum {
//		return subjects, fmt.Errorf("图片占位符数量和图片数量不匹配,占位符数量=%d,图片数量=%d", holderNum, imageNum)
//	}
//	// 解析图片
//	fmt.Println("image len=", len(doc.Images))
//	imageAddr := make([]string, holderNum)
//	for _, img := range doc.Images {
//		f, err := os.OpenFile(img.Path(), os.O_RDONLY, os.ModePerm)
//		if err != nil {
//			_ = f.Close()
//			return subjects, err
//		} else {
//			addr := "images/" + strconv.FormatInt(time.Now().UnixNano(), 10)
//			newFile, err := os.OpenFile(addr+"."+img.Format(), os.O_CREATE|os.O_WRONLY, os.ModePerm)
//			if err != nil {
//				_ = f.Close()
//				_ = newFile.Close()
//				return subjects, err
//
//			}
//			_, err = io.Copy(newFile, f)
//			_ = f.Close()
//			_ = newFile.Close()
//			imageAddr = append(imageAddr, addr)
//		}
//	}
//	// 开始替换
//	if len(imageAddr) != holderNum {
//		return subjects, fmt.Errorf("图片数量和占位符数量不一致")
//	}
//	//for k, sub := range subjects {
//	//
//	//}
//	return subjects, nil
//}
